import 'package:flutter/material.dart';

/// 重绘整个控件树
typedef void ReDraw(VoidCallback fn);


/// 画背景
typedef DrawBackground(
    Canvas canvas, Offset offset, ImageConfiguration configuration);

/// 控件更新
typedef void Update(Vary vary,double value);


enum Vary{
  width,
  height
}

/// 控件的布局
enum Layout{
  column,
  row,
  container
}

class Distance {
  double left, top, right, bottom;

  Distance(
      {this.left = 0.0, this.top = 0.0, this.right = 0.0, this.bottom = 0.0});

  Distance.all(double value)
      : this.left = value,
        this.top = value,
        this.right = value,
        this.bottom = value;

  EdgeInsets get edgeInsets {
    return EdgeInsets.fromLTRB(left, top, right, bottom);
  }
}

/// 控件描述
class Node {
  Distance padding;   // 内边距
  double _width, _height; // 控件高度，控件宽度
  double minWidth,minHeight; // 控件最小高度，控件最大高度
  String type;  // 控件类型
  String include; // 可包含的子控件类型
  Map ext;  // 控件自己的扩展数据
  NodeChildren children; // 控件的儿子信息
  Paint bgPaint;  // 背景画笔
  Paint primaryPaint; // 重点显示画笔
  Paint paint;  //普通画笔
  double _startX; // 控件X坐标起点
  double _startY; // 控件Y坐标起点
  int _index; // 控件索引
  int _parent; // 父亲控件索引
  Update _update; // 控件更新
  bool _active; // 控件激活
  Layout _layout; // 控件布局
  final _tree = 1; // 控件树顶点的索引
  static final _treeList = <Node>[]; // 控件树二维数组
  static var _mark = 1; // 控件索引自增

  Node({
    this.padding,
    @required this.type,
    this.include = "*",
    this.ext,
    bool isTree = false,
    this.primaryPaint,
    this.bgPaint,
    this.paint,
    double width,
    double height,
    this.minWidth = 0.0,
    this.minHeight = 0.0,
  })  : this._active = false,
        this._width = width,
        this._height = height {
    if (isTree) {
      _index = _tree;
      _treeList.clear();
      _treeList.add(this);
    }
    this.children = NodeChildren(this);
    ext ??= {};
    padding ??= Distance.all(0.0);
    primaryPaint ??= Paint()
      ..color = Colors.redAccent
      ..style = PaintingStyle.stroke;

    paint ??= Paint()
      ..color = Colors.blueGrey
      ..style = PaintingStyle.stroke;

    bgPaint ??= Paint()
      ..color = Colors.grey[300]
      ..style = PaintingStyle.fill;
  }

//  void _notify(Vary vary,double value){
//    _update(vary,value);
//    for (var it in children.get) {
//      it._notify(vary,value);
//    }
//  }

  double get width {
    return _width ?? parent.availableWidth;
  }

  double get height {
    return _height ?? parent.availableHeight;
  }

  set width(double value) {
    if(value  < minWidth){
      value = minWidth;
    }
    if(_width != null){
      final change = value - _width;
      _width = value;
      for (var it in children.get) {
        it._update(Vary.width,change);
      }
    }
  }

  set height(double value) {
    if(value < minHeight){
      value = minHeight;
    }
    if(_height != null){
      final change = value - _height;
      _height = value;
      for (var it in children.get) {
        it._update(Vary.height,change);
      }
    }
  }

  double get availableWidth {
    return width - padding.left - padding.right;
  }

  double get availableHeight {
    return height - padding.top - padding.bottom;
  }

  double get startX{
    switch(parent?._layout){
      case Layout.row:
        if(prev != null){
          return prev.startX + prev.width;
        }
        continue next;
        break;
      next:
      case Layout.column:
      case Layout.container:
        return parent.availableStartX;
        break;
    }
    return _startX;
  }

  double get startY{
    switch(parent?._layout){
      case Layout.column:
        if(prev !=null){
          return prev.startY + prev.height;
        }
        continue next;
      break;
      next:
      case Layout.row:
      case Layout.container:
          return parent.availableStartY;
        break;
    }
    return _startY;
  }

  double get availableStartX{
    return startX + padding.left;
  }

  double get availableStartY{
    return startY + padding.top;
  }

  // 获得当前控件的父亲
  Node get parent {
    return _treeList
        .singleWhere((n) => n._index == _parent,orElse: ()=>null);
  }

  //获得前面的一个控件
  Node get prev {
    var child = parent.children;
    var thisIndex = child._origin.indexOf(this);
    return thisIndex != 0 ? child._origin[thisIndex - 1] : null;
  }

  //获得后面的一个控件
  Node get next {
    var child = parent.children;
    var thisIndex = child._origin.indexOf(this);
    return thisIndex != child.get.length - 1
        ? child._origin[thisIndex + 1]
        : null;
  }

  // 获得顶点控件
  Node get tree {
    return _treeList.singleWhere((n) => n._index == _tree);
  }

  set active(bool value) {
    _treeList.singleWhere((n) => n._active, orElse: () => null)?._active =
        false;
    this._active = true;
  }

  bool get active {
    return _active;
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Node &&
          runtimeType == other.runtimeType &&
          _index == other._index;

  @override
  int get hashCode => _index.hashCode;

  @override
  String toString() {
    return 'Node{padding: $padding, _width: $_width, _height: $_height, type: $type, include: $include, ext: $ext, _active: $_active, children: $children, bgPaint: $bgPaint, primaryPaint: $primaryPaint, paint: $paint, startX: $_startX, startY: $_startY, _index: $_index, _parent: $_parent, _tree: $_tree}';
  }
}

/// 子控件列表类
class NodeChildren {
  var _children = <Node>[];

  Node parent;

  NodeChildren(this.parent);

  Iterable<Node> get get {
    return _children.where((n) => true);
  }

  List<Node> get _origin {
    return _children;
  }

  void add(List<Node> nodes) {
    for (var node in nodes) {
      node._parent = parent._index;
      node._index = (++Node._mark);
      _children.add(node);
      Node._treeList.add(node);
    }
  }
}

/// 所有控件的父亲类
abstract class RegisterWidget extends StatelessWidget {

  Node node; // 当前控件描述信息

  ReDraw redraw; // 重绘

  String get type; // 控件类型

  Controller controller; // 控制类

  final _widgets = <RegisterWidget>[]; // 子控件集合

  /// 子控件
  Widget get children {
    if (_widgets.length >= 2) {
      var totalLength =
      _widgets.fold<double>(0.0, (init, ele) => init += ele.node.width);
      if (totalLength > node.availableWidth) {
        node._layout = Layout.column;
        return Column(
          children: _widgets,
        );
      }
      node._layout = Layout.row;
      return Row(
        children: _widgets,
      );
    }
    node._layout = Layout.container;
    return _widgets.isEmpty ? null : _widgets.first;
  }

  /// 控件更新
  void update(Vary vary,double value);

  RegisterWidget get clone;

  /// 插入一个新的控件描述信息到父亲的描述信息下
  void insert(Offset offset, Node parent);

/// ////////////////////////////////////////////////////////////////////////////
///   消息监听
  GestureTapCallback get onTap {
    return () {
      redraw(() {
        node.active = true;
      });
    };
  }
  GestureTapDownCallback get onTapDown {}

  GestureTapUpCallback get onTapUp {}

  GestureTapCancelCallback get onTapCancel {}

  GestureTapCallback get onDoubleTap {}

  GestureLongPressCallback get onLongPress {}

  GestureDragDownCallback get onVerticalDragDown {}

  GestureDragStartCallback get onVerticalDragStart {
    return (DragStartDetails details) {
      redraw(() {
        node.active = true;
      });
    };
  }

  GestureDragUpdateCallback get onVerticalDragUpdate {}

  GestureDragEndCallback get onVerticalDragEnd {}

  GestureDragCancelCallback get onVerticalDragCancel {}

  GestureDragDownCallback get onHorizontalDragDown {}

  GestureDragStartCallback get onHorizontalDragStart {
    return (DragStartDetails details) {
      redraw(() {
        node.active = true;
      });
    };
  }

  GestureDragUpdateCallback get onHorizontalDragUpdate {}

  GestureDragEndCallback get onHorizontalDragEnd {}

  GestureDragCancelCallback get onHorizontalDragCancel {}

  GestureDragDownCallback get onPanDown {}

  GestureDragStartCallback get onPanStart {}

  GestureDragUpdateCallback get onPanUpdate {}

  GestureDragEndCallback get onPanEnd {}

  GestureDragCancelCallback get onPanCancel {}

  GestureScaleStartCallback get onScaleStart {}

  GestureScaleUpdateCallback get onScaleUpdate {}

  GestureScaleEndCallback get onScaleEnd {}

  HitTestBehavior get behavior {}

  bool get excludeFromSemantics {
    return true;
  }
/// ////////////////////////////////////////////////////////////////////////////

/// /////////////////////////////////////////////////////////////////////////////
///  控件初始化
  AlignmentGeometry get alignment {}

  Decoration get decoration {}

  Color get color {}

  BoxConstraints get constraints {}

  Matrix4 get transform {}

  EdgeInsetsGeometry get margin {}

  // 设置边框距离
  double get measure{
    return 6.0;
  }
  /// 控件自定义绘制
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    final Rect rect = offset & configuration.size;
    Rect wRect = Rect.fromLTRB(
        rect.left, rect.top, rect.left + node.width, rect.top + node.height);
    Rect nRect = Rect.fromLTRB(wRect.left + measure, wRect.top + measure,
        wRect.right - measure, wRect.bottom - measure);
    var paint = node.active ? node.primaryPaint : node.paint;
    canvas.drawRect(wRect, paint);
    canvas.drawRect(nRect, paint);
    canvas.drawLine(
        Offset(wRect.left, wRect.top), Offset(nRect.left, nRect.top), paint);
    canvas.drawLine(
        Offset(wRect.right, wRect.top), Offset(nRect.right, nRect.top), paint);
    canvas.drawLine(Offset(wRect.right, wRect.bottom),
        Offset(nRect.right, nRect.bottom), paint);
    canvas.drawLine(Offset(wRect.left, wRect.bottom),
        Offset(nRect.left, nRect.bottom), paint);
  }
/// ////////////////////////////////////////////////////////////////////////////

  /// 重要方法，控件生成
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: onTapDown,
      onTapUp: onTapUp,
      onTap: onTap,
      onTapCancel: onTapCancel,
      onDoubleTap: onDoubleTap,
      onLongPress: onLongPress,
      onVerticalDragDown: onVerticalDragDown,
      onVerticalDragStart: onVerticalDragStart,
      onVerticalDragUpdate: onVerticalDragUpdate,
      onVerticalDragEnd: onVerticalDragEnd,
      onVerticalDragCancel: onVerticalDragCancel,
      onHorizontalDragDown: onHorizontalDragDown,
      onHorizontalDragStart: onHorizontalDragStart,
      onHorizontalDragUpdate: onHorizontalDragUpdate,
      onHorizontalDragEnd: onHorizontalDragEnd,
      onHorizontalDragCancel: onHorizontalDragCancel,
      onPanDown: onPanDown,
      onPanStart: onPanStart,
      onPanUpdate: onPanUpdate,
      onPanEnd: onPanEnd,
      onPanCancel: onPanCancel,
      onScaleStart: onScaleStart,
      onScaleUpdate: onScaleUpdate,
      onScaleEnd: onScaleEnd,
      behavior: behavior,
      excludeFromSemantics: excludeFromSemantics,
      child: Container(
        width: node.width,
        height: node.height,
        padding: node.padding.edgeInsets,
        foregroundDecoration: BoxBackground(node, paint),
        color: color,
        decoration: decoration,
        constraints: constraints,
        transform: transform,
        margin: margin,
        child: children,
      ),
    );
  }

}

// 控件的控制类
class Controller {

  Controller();

  final _registerList = <RegisterWidget>[];

  String markType = "";

  // 初始化和注册控件
  Controller.register(List<RegisterWidget> list) {
    _registerList.addAll(list);
  }

  // 注册控件
  void addRegister(RegisterWidget r) {
    _registerList.add(r);
  }

  // 解释控件描述信息
  resolve(Node node, ReDraw redraw) {
    if (node == null) return null;
    RegisterWidget r = _registerList.singleWhere((e) => e.type == node.type,
        orElse: () => null);
    if (r != null) {
      r = r.clone;
      r.node = node;
      r.redraw = redraw;
      r.controller = this;
      node._update = r.update;
      if (r.node.children._origin.isNotEmpty) {
        for (var it in r.node.children.get) {
          r._widgets.add(resolve(it, redraw));
        }
      }
    }
    return r;
  }
}

/// 绘制控件背景
class BoxBackground extends Decoration {
  final Node node;
  final DrawBackground drawBackground;

  BoxBackground(this.node, this.drawBackground);

  @override
  BoxPainter createBoxPainter([VoidCallback onChanged]) {
    return MyBoxPainter(node, drawBackground);
  }
}

class MyBoxPainter extends BoxPainter {
  final Node node;
  final DrawBackground drawBackground;

  MyBoxPainter(this.node, this.drawBackground);

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    assert(configuration != null);
    assert(configuration.size != null);
    node._startX = offset.dx;
    node._startY = offset.dy;
    drawBackground(canvas, offset, configuration);
  }
}

/// 容器控件
class ContainerWidget extends RegisterWidget {
  @override
  String get type {
    return "container";
  }

  @override
  RegisterWidget get clone {
    return ContainerWidget();
  }

  /// 容器控件不可见，所以覆盖呢绘制
  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {

  }

  /// 当点击容器控件的时候插入控件
  @override
  GestureTapUpCallback get onTapUp {
    return (TapUpDetails details) {
      controller._registerList.shuffle();
      controller._registerList.shuffle();
      var r = controller._registerList.first;
//      var r = controller._registerList.singleWhere((it)=>it.type == controller.markType,orElse: ()=>null);
      if (r != null) {
        r.insert(details.globalPosition, node);
        redraw(() {});
      }
    };
  }

  @override
  void insert(Offset offset, Node parent) {}

  @override
  void update(Vary vary, double value) {

  }
}
